﻿// -----------------------------------------------------------------------
// <copyright file="HttpClientExtension.cs" company="北京正奇联讯科技有限公司">
//      Copyright 2015, ZhengQi (Beijing) Video Technology Co.,Ltd. ALL RIGHTS RESERVED 
//   Permission is hereby granted to licensees of ZhengQi (Beijing) Video Technology Co.,Ltd. 
//   products to use or abstract this computer program for the sole purpose of implementing 
//   a product based on ZhengQi (Beijing) Video Technology Co.,Ltd.products. No other rights to 
//   reproduce, use, or disseminate this computer program,whether in part or in whole, are granted. 
//   ZhengQi (Beijing) Video Technology Co.,Ltd. makes no representation or warranties with 
//   respect to the performance of this computer program, and specifically disclaims any 
//   responsibility for any damages, special or consequential, connected with the use of 
//   this program. For details, see http://www.cdv.com/
// </copyright>
// <summary>
//    HttpClient扩展类
// </summary>
// <author>HouBaoZhu</author>
// <createTime>2017/09/08 16:02</createTime>
// <version>1.0</version>
// <modify></modify>
// -----------------------------------------------------------------------
using CDV.MC.MatrixDriver.WebApp.Service;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

namespace CDV.MC.MatrixDriver.WebApp.Extensions
{
    /// <summary>
    /// HttpClient扩展类
    /// </summary>
    public static class HttpClientExtension
    {
        /// <summary>
        /// 处理GET请求
        /// </summary>
        /// <typeparam name="TResult">返回值类型</typeparam>
        /// <param name="httpClient">HttpClient对象</param>
        /// <param name="address">服务地址(终结点的address)</param>
        /// <param name="action">操作名</param>
        /// <param name="parameter">传入参数</param>
        /// <returns>TResult</returns>
        public static TResult Get<TResult>(this HttpClient httpClient, string address, string action, string parameter = "")
        {
            try
            {
                var uri = $"{address}/{action}";
                if (!string.IsNullOrWhiteSpace(parameter))
                {
                    uri += "/?" + parameter;
                }
                var response = httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
                if (response.Result.StatusCode == HttpStatusCode.OK)
                {
                    //response.Result.Content.Headers.ContentEncoding.Add("utf-8");
                    //response.Result.Content.Headers.ContentEncoding.Add("gb2312");
                    //response.Result.Content.Headers.ContentType.CharSet = "utf-8";
                    //response.Result.Content.Headers.ContentType.MediaType= "application/json";
                    var responseBody = response.Result.Content.ReadAsStringAsync();

                    var responseData = JsonConvert.DeserializeObject<TResult>(responseBody.Result);
                    //var responseData = DeserializeObject<TResult>(responseBody.Result);
                    return responseData;
                }
                return default(TResult);
            }
            catch (Exception ex)
            {
                throw HandleException(ex);
            }
        }

        /// <summary>
        /// 处理POST请求
        /// </summary>
        /// <typeparam name="TResult">返回值类型</typeparam>
        /// <param name="httpClient">HttpClient对象</param>
        /// <param name="address">服务地址(终结点的address)</param>
        /// <param name="action">操作名</param>
        /// <param name="parameter">传入参数</param>
        /// <returns>TResult</returns>
        public static TResult Post<TResult>(this HttpClient httpClient, string address, string action, object parameter)
        {
            try
            {
                var input = parameter == null ? string.Empty : JsonConvert.SerializeObject(parameter, Formatting.Indented);
                var content = new StringContent(input);
                var response = httpClient.PostAsync($"{address}/{action}", content);
                if (response.Result.StatusCode == HttpStatusCode.OK)
                {
                    var responseBody = response.Result.Content.ReadAsStringAsync();
                    var responseData = JsonConvert.DeserializeObject<TResult>(responseBody.Result);
                    return responseData;
                }
                return default(TResult);
            }
            catch (Exception ex)
            {
                throw HandleException(ex);
            }
        }

        public static string GetRemotingIP(this HttpClient httpClient)
        {
            if (httpClient.DefaultRequestHeaders.TryGetValues(HttpClientProvider.ClientIPName, out IEnumerable<string> item))
            {
                return item.FirstOrDefault() ?? string.Empty;
            }
            return string.Empty;
        }

        /// <summary>
        /// 处理异常
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <returns>包装后的异常信息</returns>
        private static Exception HandleException(Exception ex)
        {
            Console.WriteLine(ex.ToString());

            var innerException = ex.InnerException;
            while (innerException != null)
            {
                if (innerException is SocketException)
                {
                    var socketEx = innerException as SocketException;
                    if (socketEx.ErrorCode == 10061)
                    {
                        var server = Regex.Match(socketEx.Message, @"\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}:\d+");
                        return new Exception($"无法连接到服务器[{server.Value}]，请确认网络状态或服务器主机状态！", socketEx);
                    }
                }

                innerException = innerException.InnerException;
            }

            return ex;
        }


        public static T DeserializeObject<T>(string text)
        {
            using (var memStream = new MemoryStream(Encoding.GetEncoding(936).GetBytes(text)))
            using (var reader = new StreamReader(memStream))
            {
                var serializer = new JsonSerializer();
                return (T)serializer.Deserialize(reader, typeof(T));
            }
        }
    }
}
